package com.blueocean_health.care.management.service.order_service_info;

import java.time.format.DateTimeParseException;
import java.util.*;

import com.blueocean_health.care.management.domain.ordervo.OrderServiceNurseInfoVo;
import com.blueocean_health.care.management.em.OrderTypeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.blueocean_health.care.management.common.LocalManager;
import com.blueocean_health.care.management.common.base.em.TimeType;
import com.blueocean_health.care.management.common.base.time.TimeUtils;
import com.blueocean_health.care.management.domain.base.OrderServiceNurseInfo;
import com.blueocean_health.care.management.domain.base.SysResult;
import com.blueocean_health.care.management.domain.base.SysResultByPage;
import com.blueocean_health.care.management.domain.base.User;
import com.blueocean_health.care.management.domain.dto.SelectNurseDto;
import com.blueocean_health.care.management.domain.dto.SelectNurseRespDto;
import com.blueocean_health.care.management.em.LocalManagerType;
import com.blueocean_health.care.management.em.SexEnum;
import com.blueocean_health.care.management.exception.OrderServiceException;
import com.blueocean_health.care.management.mapper.OrderServiceNurseInfoMapper;

@Service
public class SelectNurseServiceImpl implements SelectNurseService {
	
	/** 最大服务人数 */
	@Value("${work.service.max}")
	private Integer workServiceMax;
	/** 最大服务人数-提示 */
	@Value("${work.service.maxMsg}")
	private String workServiceMaxMsg;
	/** 一对一服务冲突-提示 */
	@Value("${work.service._1}")
	private String workService_1;
    /** 二对一服务冲突-提示 */
    @Value("${work.service._2}")
    private String workService_2;
	/** 男护工不能服务女患者-提示 */
	@Value("${work.gender_conflicts}")
	private String gender_conflicts;
	
	@Autowired
	private OrderServiceNurseInfoMapper orderServiceNurseInfoMapper;

	@Override
	public SysResult queryNurse(SelectNurseDto selectNurseDto) throws OrderServiceException {
		//数据验证
		String serviceType = selectNurseDto.getServiceType();
		if(serviceType == null || !serviceType.matches("^[1-6]$")){
			throw new OrderServiceException("service type error");
		}
		if(selectNurseDto.getBeginTime() == null || selectNurseDto.getEndTime() == null) {
			throw new OrderServiceException("The start time or end time is empty");
		}
		try {
			if(!TimeUtils.compare(selectNurseDto.getBeginTime(), selectNurseDto.getEndTime(), TimeType.yyyy_MM_dd_HH_mm_ss)) {
				throw new OrderServiceException("The end time must be greater than the start time");
			}
		} catch (DateTimeParseException e) {
			throw new OrderServiceException("Time type error", e);
		}
		
		Calendar stime = Calendar.getInstance();
		stime.setTime(TimeUtils.getDateByString(selectNurseDto.getBeginTime(), TimeType.yyyy_MM_dd_HH_mm_ss));
		Calendar etime = Calendar.getInstance();
		etime.setTime(TimeUtils.getDateByString(selectNurseDto.getEndTime(), TimeType.yyyy_MM_dd_HH_mm_ss));
		
		//1.获取所有符合条件的护工列表
		User user = LocalManager.getVal(LocalManagerType.USER_WEB);
		String hospital = user.getHospitalId();
		selectNurseDto.setHospital(hospital);
        String sort = selectNurseDto.getSort();
		Boolean sortFlag = "age asc".equals(sort) || "age desc".equals(sort);
		if (!sortFlag){
			selectNurseDto.setSort(null);
		}
		List<SelectNurseRespDto> nurseList = orderServiceNurseInfoMapper.selectAllNurse(selectNurseDto);
		//2.获取所有的工作中的护工列表
        // （包含退款信息，但是没有进行垃圾数据过滤）
		List<OrderServiceNurseInfoVo> workingNurseList = orderServiceNurseInfoMapper.selectNurseByWorking(hospital,selectNurseDto.getBeginTime(), selectNurseDto.getEndTime());
        //对含有退款时间的数据和垃圾数据（老version的数据）进行处理
        List<OrderServiceNurseInfoVo> workingNurseListAndRefund = new ArrayList<>();
        Long paramStart = TimeUtils.getDateByString(selectNurseDto.getBeginTime(),TimeType.yyyy_MM_dd_HH_mm_ss).getTime();
        Long paramEnd = TimeUtils.getDateByString(selectNurseDto.getEndTime(),TimeType.yyyy_MM_dd_HH_mm_ss).getTime();

        workingNurseList.forEach(info -> {
				/*if (info.getIsActive() == null && info.getRefundTime() == null){
					workingNurseListAndRefund.add(info);
				}else if (info.getRefundTime().getTime() > TimeUtils.getDateByString(selectNurseDto.getBeginTime(), TimeType.yyyy_MM_dd_HH_mm_ss).getTime() && info.getIsActive() == 1){
					workingNurseListAndRefund.add(info);
				}*/
				if (info.getRefundStart()!=null && info.getRefundEnd()!=null){
                    //退前面
                    if (info.getRefundStart().getTime() == info.getStartTime().getTime() && info.getRefundEnd().getTime() != info.getEndTime().getTime()){
                    	if (paramEnd > info.getRefundEnd().getTime()){
							workingNurseListAndRefund.add(info);
						}
                    }else if (info.getRefundStart().getTime() != info.getStartTime().getTime() && info.getRefundEnd().getTime() == info.getEndTime().getTime()){
                        //退后面
						if (paramStart < info.getRefundStart().getTime()){
							workingNurseListAndRefund.add(info);
						}
                    }else if (info.getRefundStart().getTime() != info.getStartTime().getTime() && info.getRefundEnd().getTime() != info.getEndTime().getTime()) {
                        //退中间
						if (paramStart < info.getRefundStart().getTime() || paramEnd > info.getRefundEnd().getTime()){
							workingNurseListAndRefund.add(info);
						}
                    }else if (info.getRefundStart().getTime() == info.getStartTime().getTime() && info.getRefundEnd().getTime() == info.getEndTime().getTime()){
                        //全退，排除
                    }else{

                    }
                }else{
					//退款信息是空的时候
					workingNurseListAndRefund.add(info);
				}

        });

		Map<String, List<OrderServiceNurseInfoVo>> workingMap = new HashMap<>();
        workingNurseListAndRefund.forEach(nurseInfo -> {
			List<OrderServiceNurseInfoVo> tempList = null;
			if(workingMap.containsKey(nurseInfo.getWorkerId())){
				tempList = workingMap.get(nurseInfo.getWorkerId());
			}else{
				tempList = new ArrayList<>();
				workingMap.put(nurseInfo.getWorkerId(), tempList);
			}
			tempList.add(nurseInfo);
		});
		//3.交叉集合
		List<SelectNurseRespDto> resList = new ArrayList<>();
        List<SelectNurseRespDto> finresList = new ArrayList<>();
        //获取每个护工所有最新版本的订单明细中，结束时间最晚的集合
        List<OrderServiceNurseInfoVo> allMaxVersionEndtime = orderServiceNurseInfoMapper.getAllMaxVersionEndtimeNew(hospital);
       allMaxVersionEndtime.forEach(nurseInfo -> {
           if (nurseInfo.getRefundStart() != null && nurseInfo.getRefundEnd() != null ){
			   //本条明细全退，排除这条的时间
			   if (nurseInfo.getRefundStart().getTime() == nurseInfo.getStartTime().getTime() && nurseInfo.getRefundEnd().getTime() == nurseInfo.getEndTime().getTime()){
				   nurseInfo.setStartTime(null);
			   }else if (nurseInfo.getRefundStart().getTime() == nurseInfo.getStartTime().getTime() && nurseInfo.getRefundEnd().getTime() != nurseInfo.getEndTime().getTime()){
				   //退前面，结束时间不受影响
			   }else if (nurseInfo.getRefundStart().getTime() != nurseInfo.getStartTime().getTime() && nurseInfo.getRefundEnd().getTime() == nurseInfo.getEndTime().getTime()){
				   //退后面，结束时间就是退款的开始时间
				   nurseInfo.setEndTime(nurseInfo.getRefundStart());
			   }else if (nurseInfo.getRefundStart().getTime() != nurseInfo.getStartTime().getTime() && nurseInfo.getRefundEnd().getTime() != nurseInfo.getEndTime().getTime()) {
				   //退中间，结束时间不受影响
			   }
		   }
        });


        //找打最晚的那个结束时间
		Map<String,OrderServiceNurseInfoVo> maxEndTimeMap = new HashMap<>();
        allMaxVersionEndtime.forEach(orderServiceNurseInfo -> {
            if (orderServiceNurseInfo.getStartTime() != null){
            	//找出最晚的时间
				OrderServiceNurseInfoVo oldvo = maxEndTimeMap.get(orderServiceNurseInfo.getWorkerId());
            	if (oldvo == null){
					maxEndTimeMap.put(orderServiceNurseInfo.getWorkerId(),orderServiceNurseInfo);
				}else{
					Date oldTime = oldvo.getEndTime();
					Date newTime = orderServiceNurseInfo.getEndTime();
					if (newTime.getTime() >= oldTime.getTime()){
						maxEndTimeMap.put(orderServiceNurseInfo.getWorkerId(),orderServiceNurseInfo);
					}
				}
            }
        });
        //处理一下重复的信息
		/*Iterator<SelectNurseRespDto> it = resList.iterator();
		while(it.hasNext()){
			SelectNurseRespDto nurse = it.next();
			
		}*/

		//手动分页啦
        //如果是按照下岗时间，需要拿出所有的重新去排序之后再分页
		int first = 0;
		int end = nurseList.size();
		//如果是按照年龄，直接分页
        if (sortFlag){
            first = (selectNurseDto.getPage() - 1) * selectNurseDto.getPageSize();
            end = (first + selectNurseDto.getPageSize() > nurseList.size() ? nurseList.size() : first + selectNurseDto.getPageSize());
        }
		for (int i = first; i < end; i++) {
			SelectNurseRespDto dto = nurseList.get(i);
			if(workingMap.containsKey(dto.getWorkerId())){
			    if(workingMap.get(dto.getWorkerId()).size() > 0){
                    serviceType = workingMap.get(dto.getWorkerId()).get(0).getServiceType();
                }

                if("1".equals(serviceType) ){
				    //一对一服务,
					dto.setWhetherUsed(false);
					dto.setReason(workService_1);
                } else if ("2".equals(serviceType)) {
                    //二对一服务,
                    dto.setWhetherUsed(false);
                    dto.setReason(workService_2);
                }  else if ("3".equals(serviceType)) {
					//一对多 服务,
					dto.setWhetherUsed(false);
					dto.setReason("该护工正在一对多服务中");
				} else if ("5".equals(serviceType)) {
					//单项服务,
					dto.setWhetherUsed(false);
					dto.setReason("该护工正在单项服务中");
				} else {//对多服务, 精准计算, 按照半个小时的时间单位

					/*{//方式一
						List<OrderServiceNurseInfo> list = workingMap.get(dto.getWorkerId());
						while(true){
							if(stime.getTimeInMillis() > etime.getTimeInMillis()) break;
							
							
						}
					}*/

                    {//方式二
                        if (workingMap.get(dto.getWorkerId()).size() >= workServiceMax) {
                            dto.setWhetherUsed(false);
                            dto.setReason(workServiceMaxMsg);
                        }
                    }

                }

				dto.setCurrentTask(workingMap.get(dto.getWorkerId()).size());
				//dto.setLastLaidoffDate(workingMap.get(dto.getWorkerId()).get(0).getEndTime());
				//dto.setLastLaidoffTime(TimeUtils.getStringByDate(workingMap.get(dto.getWorkerId()).get(0).getEndTime(), TimeType.yyyy_MM_dd_HH_mm_ss));
			}else {
                //Date earliest = TimeUtils.getDateByString("1970-01-01 08:00:00",TimeType.yyyy_MM_dd_HH_mm_ss);
                //dto.setLastLaidoffDate(earliest);
            }

            //男护工不能服务女患者
            if(SexEnum.MAN.getKey().equals(dto.getSex()) && SexEnum.WOMEN.getKey().equals(selectNurseDto.getPatientSex())){
                dto.setWhetherUsed(false);
                dto.setReason(gender_conflicts);
            }

            //set每个护工的最近下岗时间
            if (maxEndTimeMap.containsKey(dto.getWorkerId())){
                Date maxendTime = maxEndTimeMap.get(dto.getWorkerId()).getEndTime();
                dto.setLastLaidoffDate(maxendTime);
                dto.setLastLaidoffTime(TimeUtils.getStringByDate(maxendTime,TimeType.yyyy_MM_dd_HH_mm_ss));
            }else {
                Date earliest = TimeUtils.getDateByString("1970-01-01 08:00:00",TimeType.yyyy_MM_dd_HH_mm_ss);
                dto.setLastLaidoffDate(earliest);
                dto.setLastLaidoffTime("无服务记录");
            }
			resList.add(dto);
		}

        //按照下工时间，重新排序
		if (!sortFlag){
            Boolean timeSortFlag = "lastLaidoffTime asc".equals(sort);
            if (timeSortFlag){
                resList.sort((o1, o2) -> o1.getLastLaidoffDate().compareTo(o2.getLastLaidoffDate()));
            }else {
				resList.sort((o1, o2) -> o2.getLastLaidoffDate().compareTo(o1.getLastLaidoffDate()));
			}
            //分页
            first = (selectNurseDto.getPage() - 1) * selectNurseDto.getPageSize();
            end = (first + selectNurseDto.getPageSize() > nurseList.size() ? nurseList.size() : first + selectNurseDto.getPageSize());
            for (int i = first; i < end; i++) {
                finresList.add(resList.get(i));
            }
            return SysResultByPage.ok(finresList, nurseList.size());
        }

        finresList.addAll(resList);
		return SysResultByPage.ok(finresList, nurseList.size());
	}

}
